from django.shortcuts import render, redirect
from django.http import HttpResponse, JsonResponse
from k8sManage.models import ClusterInfo, KubeConfig
from utils.auth import login_auth, login_required, conn_k8s_api
from utils.dateformat import dt_format
from utils.node_data import node_resource
from kubernetes import client


# Create your views here.

@login_required
def index(request):
    if request.method == "GET":
        auth_type = request.session.get("auth_type", False)
        conn_k8s_api(request, auth_type=auth_type)
        core_api = client.CoreV1Api()
        pv_list = []
        for pv in core_api.list_persistent_volume().items:
            pv_name = pv.metadata.name
            capacity = pv.spec.capacity["storage"]  # 返回字典对象
            access_modes = pv.spec.access_modes
            reclaim_policy = pv.spec.persistent_volume_reclaim_policy
            status = pv.status.phase
            if pv.spec.claim_ref is not None:
                pvc_ns = pv.spec.claim_ref.namespace
                pvc_name = pv.spec.claim_ref.name
                claim = "%s/%s" % (pvc_ns, pvc_name)
            else:
                claim = "未关联PVC"
            storage_class = pv.spec.storage_class_name
            create_time = dt_format(pv.metadata.creation_timestamp)

            data = {"pv_name": pv_name, "capacity": capacity, "access_modes": access_modes,
                    "reclaim_policy": reclaim_policy, "status": status,
                    "claim": claim, "storage_class": storage_class, "create_time": create_time}
            pv_list.append(data)
        node_resources = node_resource(core_api)
        return render(request, 'index.html',{'pv_list': pv_list,'node_resources': node_resources})

@login_required
def node_resource_api(request):
    if request.method == "GET":
        auth_type = request.session.get("auth_type", False)
        conn_k8s_api(request, auth_type=auth_type)
        core_api = client.CoreV1Api()
        node_resources = node_resource(core_api)
        return JsonResponse(node_resources)


def login(request):
    if request.method == "GET":
        clusters = ClusterInfo.objects.all()  # 获取所有集群
        return render(request, "login.html", {"data": clusters})

    if request.method == "POST":
        # print(request.POST)
        auth_type = request.POST.get("auth_type")
        cluster_name = request.POST.get("cluster_name")
        # print(auth_type, cluster_name)
        cluster_address = ClusterInfo.objects.get(cluster_name=cluster_name).cluster_address
        if auth_type == "token":
            token = request.POST.get("token")
            conn_res = login_auth(cluster_host=cluster_address, token=token)
            print(conn_res)
            if conn_res['code'] == 200:
                request.session["is_login"] = True
                request.session["auth_type"] = "token"
                request.session["token"] = token
                request.session["cluster_name"] = cluster_name
            return JsonResponse(conn_res)
        elif auth_type == "config":
            file_obj = request.FILES.get('file')
            try:
                kubeconfig = file_obj.read().decode()
                # print(kubeconfig)
                conn_res = login_auth(cluster_host=cluster_address, kubeconfig=kubeconfig)
                print(conn_res)
            except Exception as e:
                return JsonResponse({"code": 400, "msg": "文件类型无效！"})
            print(conn_res['code'])
            if conn_res['code'] == 200:
                import random, hashlib
                string = str(random.random()).split('.')[1]
                hash_string = hashlib.md5(string.encode(encoding='utf-8'))
                token = hash_string.hexdigest()
                KubeConfig.objects.create(
                    auth_type="kubeconfig",
                    cus_token=token,
                    config_text=kubeconfig
                )
                request.session["is_login"] = True
                request.session["auth_type"] = "kubeconfig"
                request.session["token"] = token
                request.session["cluster_name"] = cluster_name
            return JsonResponse(conn_res)


def logout(request):
    request.session.flush()
    return redirect(login)


@login_required
def ns_api(request):
    if request.method == "GET":
        auth_type = request.session.get("auth_type", False)
        conn_k8s_api(request, auth_type=auth_type)
        core_api = client.CoreV1Api()
        ns_list = []
        try:
            for ns in core_api.list_namespace().items:  # items返回一个对象，类LIST（[{命名空间属性},{命名空间属性}] ），每个元素是一个类字典（命名空间属性），操作类字典
                name = ns.metadata.name
                labels = ns.metadata.labels
                create_time = ns.metadata.creation_timestamp
                namespace = {"name": name, "labels": labels, "create_time": create_time}
                ns_list.append(namespace)
            code = 0
            msg = "namespace获取成功！"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "无权限！"
            else:
                msg = "查询失败！"
            code = 1
        return JsonResponse({"code": code, "data": ns_list, "msg": msg})


@login_required
def editor(request):
    data = {}
    name = request.GET.get("name")
    namespace = request.GET.get("namespace")
    res_type = request.GET.get("res_type")
    data['name'] = name
    data['namespace'] = namespace
    data['res_type'] = res_type
    return render(request, 'editor.html', {'data': data})


# 将从k8s获取的byte内容转换为yaml输出
import json, yaml


def convert_yaml(result):
    if isinstance(result, bytes):
        result = result.decode()  # bytes 转 string
        json_result = json.loads(result)  # string 转 json
        yaml_result = yaml.safe_dump(json_result)  # json 转 yaml
        return yaml_result


@login_required
def export_res_yaml(request):
    if request.method == "GET":
        # 获取namespace、资源类型、资源名称
        namespace = request.GET.get("namespace")
        res_type = request.GET.get("res_type")
        name = request.GET.get("name")
        # 连接k8s集群并实例化
        auth_type = request.session.get("auth_type", False)
        conn_k8s_api(request, auth_type=auth_type)
        core_api = client.CoreV1Api()
        apps_api = client.AppsV1Api()
        networking_api = client.NetworkingV1Api()
        storage_api = client.StorageV1Api()

        code = 0
        msg = "获取yaml成功！"
        result = ""
        if res_type == "namespace":
            try:
                result = core_api.read_namespace(name=name, _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "pv":
            try:
                result = core_api.read_persistent_volume(name=name, _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "deployment":
            try:
                result = apps_api.read_namespaced_deployment(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "statefulset":
            try:
                result = apps_api.read_namespaced_stateful_set(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "daemonset":
            try:
                result = apps_api.read_namespaced_daemon_set(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "pod":
            try:
                result = core_api.read_namespaced_pod(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "service":
            try:
                result = core_api.read_namespaced_service(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "ingress":
            try:
                result = networking_api.read_namespaced_ingress(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "configmap":
            try:
                result = core_api.read_namespaced_config_map(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "secret":
            try:
                result = core_api.read_namespaced_secret(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "pvc":
            try:
                result = core_api.read_namespaced_persistent_volume_claim(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        elif res_type == "replicaset":
            try:
                result = apps_api.read_namespaced_replica_set(namespace=namespace, name=name,
                                                             _preload_content=False).read()
                result = convert_yaml(result)
            except Exception as e:
                code = 1
                msg = "获取yaml信息失败！"
        else:
            code = 1
            msg = "资源类型有误！"
        data = {'code': code, 'msg': msg, 'data': result}
        return JsonResponse(data)


@login_required
def apply_yaml(request):
    if request.method == "POST":
        yaml_content = request.POST.get("yaml_content")

        auth_type = request.session.get("auth_type", False)
        conn_k8s_api(request, auth_type=auth_type)
        core_api = client.CoreV1Api()
        apps_api = client.AppsV1Api()
        networking_api = client.NetworkingV1Api()
        storage_api = client.StorageV1Api()

        code = 0
        msg = "提交成功！"
        result = ""
        content = yaml.safe_load(yaml_content)  # yaml 转 dict
        print(content)
        kind = content['kind']
        namespace = content['metadata']['namespace']
        name = content['metadata']['name']
        if kind == "Namespace":
            try:
                core_api.patch_namespace(body=content, name=name)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "PersistentVolume":
            try:
                core_api.patch_persistent_volume(body=content, name=name)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "Deployment":
            try:
                apps_api.patch_namespaced_deployment(body=content, name=name, namespace=namespace)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "StatefulSet":
            try:
                apps_api.patch_namespaced_stateful_set(body=content, name=name, namespace=namespace)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "DaemonSet":
            try:
                apps_api.patch_namespaced_daemon_set(body=content, name=name, namespace=namespace)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "Pod":
            try:
                core_api.patch_namespaced_pod(body=content, name=name, namespace=namespace)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "Service":
            try:
                core_api.patch_namespaced_service(body=content, name=name, namespace=namespace)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "Ingress":
            try:
                networking_api.patch_namespaced_ingress(body=content, name=name, namespace=namespace)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "ConfigMap":
            try:
                core_api.patch_namespaced_config_map(body=content, name=name, namespace=namespace)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "Secret":
            try:
                core_api.patch_namespaced_secret(body=content, name=name, namespace=namespace)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        elif kind == "PersistentVolumeClaim":
            try:
                core_api.patch_namespaced_persistent_volume_claim(body=content, name=name, namespace=namespace)
            except Exception as e:
                code = 1
                msg = "应用失败！请检查yaml文件格式！"
        else:
            code = 1
            msg = "资源类型有误！"
        data = {'code': code, 'msg': msg}
        return JsonResponse(data)
